package com.jin.webvideo.websocket.shareroom;

import com.jin.webvideo.websocket.shareroom.entity.BinMessage;
import com.jin.webvideo.websocket.shareroom.entity.BinMessageHandler;
import com.jin.webvideo.websocket.shareroom.entity.MsgIO;
import com.jin.webvideo.websocket.shareroom.entity.RoomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.util.Map;

@Component
public class ShareRoomHandler extends AbstractWebSocketHandler {
    @Autowired
    ShareRoomManager manager;
    BinMessageHandler handler = new BinMessageHandler();
    /**
     * 成功连接WebSocket后执行
     * @param session session
     * @throws Exception Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Map<String,Object> map = session.getAttributes();
        long roomid = (long) map.get("roomId");
        ShareRoom room = manager.findByRoomId(roomid);
        String account = (String) map.get("account");
        if (room != null){
            if (!RoomUtil.join(room, account, session)) {
                session.close();
            }
        }
    }

    /**
     * 在两端WebSocket connection都关闭或transport error发生后执行
     * @param session     session
     * @param closeStatus closeStatus
     * @throws Exception Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        Map<String, Object> map = session.getAttributes();
        String account = map.get("account").toString();
        long roomid = (long)map.get("roomId");
        ShareRoom room = manager.findByRoomId(roomid);
        if (room != null){
            if (RoomUtil.leave(room, account)) {
                manager.closeRoom(room);
            }
        }
    }

    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        BinMessage bin = MsgIO.read(message.getPayload());
        Map<String, Object> map = session.getAttributes();
        String account = map.get("account").toString();
        ShareRoom room = manager.findByRoomId((long) map.get("roomId"));
        if (room == null){
            session.close();
            return;
        }
        BinMessage out = handler.handle(bin, room);
        if (out.getBroadcast() == BinMessage.BROADCAST_SEND_SELF) {
            RoomUtil.send(session, MsgIO.write(out));
            return;
        }
        if (out.getBroadcast() == BinMessage.BROADCAST_SYSTEM) {
            RoomUtil.systemBroadcast(room, MsgIO.write(out));
            return;
        }
        if (out.getBroadcast() == BinMessage.BROADCAST_EXCEPT_SELF) {
            RoomUtil.broadcast(room, account, MsgIO.write(out));
            return;
        }
    }

    /**
     * Whether the WebSocketHandler handles partial messages. If this flag is set to
     * {@code true} and the underlying WebSocket server supports partial messages,
     * then a large WebSocket message, or one of an unknown size may be split and
     * maybe received over multiple calls to
     * {@link #handleMessage(WebSocketSession, WebSocketMessage)}. The flag
     * {@link WebSocketMessage#isLast()} indicates if
     * the message is partial and whether it is the last part.
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
